package org.onion.pattern.sample.order.service;

import lombok.SneakyThrows;
import org.onion.pattern.event.domain.annotation.ExternalEventSignal;
import org.onion.pattern.event.spring.external.rocketmq.consume.RocketApplicationEvent;
import org.onion.pattern.event.spring.external.rocketmq.consume.RocketMsgMetadata;
import org.onion.pattern.sample.order.doamin.pay.PayOrder;
import org.onion.pattern.sample.order.doamin.pay.PayOrderId;
import org.onion.pattern.sample.order.doamin.pay.PayRepository;
import org.onion.pattern.sample.order.doamin.pay.PayService;
import org.onion.pattern.sample.order.doamin.pay.event.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class PayServiceImpl implements PayService {

    @Autowired
    private ApplicationEventPublisher publisher;
    @Autowired
    private PayRepository repository;

    @SneakyThrows
    @Override
    public Long pay() {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                System.out.println("pay 事务提交完成 ！！！");
            }
        });

        PayOrder payOrder = new PayOrder();
        payOrder.setId(new PayOrderId(System.currentTimeMillis()));
        payOrder.setStatus("PAY");
        payOrder.setTradeNo(UUID.randomUUID().toString());
        repository.saveOrder(payOrder);

        // 支付完成， 生成支付订单
//        TimeUnit.SECONDS.sleep(1);

        PayEvent payEvent = new PayEvent();
        payEvent.setOrder(payOrder);

        //简单通知 、 内部通知
        publisher.publishEvent(payEvent);

        return payOrder.getId().getId();
    }

    @Override

    public Long pay2() {
        PayOrder payOrder = new PayOrder();
        payOrder.setId(new PayOrderId(System.currentTimeMillis()));
        payOrder.setStatus("PAY");
        payOrder.setTradeNo(UUID.randomUUID().toString());
        repository.saveOrder(payOrder);

        // 支付完成， 生成支付订单
//        TimeUnit.SECONDS.sleep(1);

        PayEvent2 payEvent = new PayEvent2();
        payEvent.setOrder(payOrder);

        //简单通知 、 内部通知
        publisher.publishEvent(payEvent);

        return payOrder.getId().getId();
    }

    @Override
    public Long pay3() {
        PayOrder payOrder = new PayOrder();
        payOrder.setId(new PayOrderId(System.currentTimeMillis()));
        payOrder.setStatus("PAY");
        payOrder.setTradeNo(UUID.randomUUID().toString());
        repository.saveOrder(payOrder);

        // 支付完成， 生成支付订单
//        TimeUnit.SECONDS.sleep(1);

        PayEvent3 payEvent = new PayEvent3();
        payEvent.setOrder(payOrder);

        //事务完成后提交， 从源头处理。
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                publisher.publishEvent(payEvent);
            }
        });


        return payOrder.getId().getId();
    }

    @Override
    public Long pay4() {
        PayEvent4 payEvent = new PayEvent4();
        //简单通知 、 内部通知
        publisher.publishEvent(payEvent);

        PayOrder payOrder = new PayOrder();
        payOrder.setId(new PayOrderId(System.currentTimeMillis()));
        payOrder.setStatus("PAY");
        payOrder.setTradeNo(UUID.randomUUID().toString());
        repository.saveOrder(payOrder);

        // 支付完成， 生成支付订单
//        TimeUnit.SECONDS.sleep(1);

        payEvent.setOrder(payOrder);

        return payOrder.getId().getId();
    }

    @Override
    public Long pay5() {
        PayOrder payOrder = new PayOrder();
        payOrder.setId(new PayOrderId(System.currentTimeMillis()));
        payOrder.setStatus("PAY");
        payOrder.setTradeNo(UUID.randomUUID().toString());
        repository.saveOrder(payOrder);

        // 支付完成， 生成支付订单
//        TimeUnit.SECONDS.sleep(1);

        PayEvent5 payEvent = new PayEvent5();
        payEvent.setOrder(payOrder);

        //简单通知 、 内部通知
        publisher.publishEvent(payEvent);

        return payOrder.getId().getId();
    }

    @SneakyThrows
    @Override
    @ExternalEventSignal
    public void refund() {
        // 退款
//        TimeUnit.SECONDS.sleep(1);
        PayRefundEvent payEvent = new PayRefundEvent();
        payEvent.setOrder(new PayOrder());
        //外部通知
        publisher.publishEvent(payEvent);
    }

    @Override
    public void refundMock() {
        PayRefundEvent payEvent = new PayRefundEvent();
        payEvent.setOrder(new PayOrder());
        RocketApplicationEvent<PayRefundEvent> event = new RocketApplicationEvent<>(payEvent,new RocketMsgMetadata());
        //外部通知
        publisher.publishEvent(event);
    }

    @SneakyThrows
    @Override
    public void cancel() {
        // 订单撤销
        TimeUnit.SECONDS.sleep(1);

        PayCancelEvent payEvent = new PayCancelEvent();
        payEvent.setOrder(new PayOrder());
        //内部通知
        //事务提交后发送 ..
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                //在事务提交后发送...
                publisher.publishEvent(payEvent);
            }
        });

    }






}
